from bson.objectid import ObjectId
from bson import json_util
from pymongo import MongoClient

import pymongo
import logging
import uuid

import setting
import base64
import json
import datetime


logger = logging.getLogger('mongodb')


class DBClient(object):
    def __init__(self, *args, **kwargs):
        self.db_name = kwargs.get('db_name', setting.DB_NAME)
        self.db_url = kwargs.get('db_url', setting.DB_URL)
        self.col_name = kwargs.get("col_name", "config")
        self.config_col_name = "config"
        self.task_col_name = "task"
        self.right_col_name = "right"

    def get_client(self, _url=None):
        if _url is not None:
            url = _url
        else:
            url = self.db_url
        return MongoClient(url)

    def get_db(self, db_name=None):
        if db_name is None:
            db_name = self.db_name
        client = self.get_client()
        return client[db_name]


    def update_config_record(self, name, value):
        col = self.get_db()[self.config_col_name]
        names = name.strip().split(".")
        first_name = names[0]
        if col.find_one({"name": first_name}):
            result = col.find_one({"name": first_name})
        else:
            result = col.insert_one({"name": first_name, "data": ""})
        if result["data"]:
            data = json.loads(base64.b64decode(result["data"]).decode("utf8"))
        else:
            data = {}

        _data = data
        for n in range(1, len(names) - 1):
            try:
                _data = _data[names[n]]
            except KeyError:
                _data[names[n]] = {}
                _data = _data[names[n]]
        _data[names[-1]] = value
        col.find_one_and_update({'_id': ObjectId(result['_id'])},
                {'$set': {'data': base64.b64encode(json.dumps(data).encode("utf8"))}})

    def find_config_record(self, name=None):
        col = self.get_db()[self.config_col_name]
        if name is not None:
            names = name.strip().split(".")
            first_name = names[0]
            result = col.find_one({"name": first_name})
            data = json.loads(base64.b64decode(result["data"]).decode("utf8"))
            if result:
                for n in range(1, len(names)):
                    data = data[names[n]]
            return data
        else:
            data = []
            for name in ['tale', ]:
                data.append({"name": name, "data": self.find_config_record(name)})
            return data

    def get_task(self, id=None):
        col = self.get_db()[self.task_col_name]
        data = []
        if id is None:
            for _data in col.find().sort([("now",pymongo.DESCENDING)]):
                _data["_id"] = str(_data['_id'])
                _data["now"] = _data["now"]# + datetime.timedelta(hours=8)
                data.append(_data)
            return data
        else:
            _data = col.find_one({"_id": ObjectId(id)})
            _data["_id"] = str(_data['_id'])
            _data["now"] = _data["now"]# + datetime.timedelta(hours=8)
            return _data

    def insert_task(self, data):
        col = self.get_db()[self.task_col_name]
        col.insert_one(data)

    def update_task(self, task):
        col = self.get_db()[self.task_col_name]
        col.update({"_id": ObjectId(task['_id'])}, {"$set": {"steps": task["steps"], "status": task["status"]}})


    def update_right(self, right):
        col = self.get_db()[self.right_col_name]
        if "_id" in right.keys():
            _r = col.find_one({"_id": ObjectId(right["_id"])})
            if "ret" in right.keys():
                col.update({"_id": ObjectId(right["_id"])}, {"$set": {"ret": right['ret']}})
            else:
                col.update({"_id": ObjectId(right["_id"])}, {"$set": {"time": right['time']}})
        else:
            col.insert_one(right)
